//microcommand define lnnpuaname
const start = 0xe000
const map = new Map()
let cp = start
function add(name, opt) {
  if (!name || name.includes("/")) name = "<OBSOLETE> " + name.replace(/\//g, "")
  name = name.replace(/_/g, " ").replace(/\s+/g, " ")
  map.set(cp++, name)
}

function fill(bits) {
  cp = -(-cp >> bits << bits)
}

function* range(s, e) {
  if (typeof e !== "number") {
    e = s
    s = 0
  }
  for (let i = s; i < e; i++) yield i
}

/** template string, but false, null, and undefined will be treated as the empty string */
function tS(segs, ...interp) {
  return interp.reduce(
    (a, c, i) => a + (c === false || c == null ? "" : c) + segs[i + 1],
    segs[0]
  )
}

function tA(...args) {
  return tS(...args).trim().split(/\s+/g)
}

const numWords = tA`ZERO ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE TEN ELEVEN TWELVE THIRTEEN FOURTEEN FIFTEEN`
const letters = Array.from({ length: 26 }, (_, i) => String.fromCharCode(65 + i))

//label("LNNCrypt")
for (const i of range(16))
  add(tS`LNNCRYPT DIGIT ${numWords[i]}`)
for (const l of tA`A O E I U Y EH AI EI AO OU`)
  add(`LNNCRYPT LETTER ${l}`)
for (const i of range(5))
  add(`LNNCRYPT COMBINING TONE ${numWords[i]}`)
for (const l of tA`B P M F D T N L G K NG H J Q W X ZH CH R SH Z C V S`)
  add(`LNNCRYPT LETTER ${l}`)
for (const w of tA`THE OF ON IN TO`)
  add(`LNNCRYPT SYMBOL ${w}`)
fill(4)

//label("LNNZHYZ")
for (const i of range(16))
  add(tS`LNNZHYZ DIGIT ${numWords[i]}`)
for (const l of tA`W B P M F D T N L G K H J Q X ZH CH SH R Z C S V I U Y E A O`)
  add(`LNNZHYZ LETTER ${l}`)
add(`LNNZHYZ MODIFIER LETTER ER`)
add(`LNNZHYZ HYPHEN`)
add(`LNNZHYZ CAPITAL MARK`)
for (const i of range(1, 5))
  add(`LNNZHYZ SYLLABLE TAIL TONE ${numWords[i]}`)
for (const [t, ll] of Object.entries({
  GLIDE: tA`I U Y`,
  VOWEL: tA`E A O EH`,
  CODA: tA`I U N NG R`,
}))
  for (const l of ll) add(`LNNZHYZ ${t} SIGN ${l}`)
for (const l of tA`M NG`)
  add(`LNNZHYZ SYLLABLE TAIL ${l}`)
fill(4)

//label("LNNZHYZ Finals")
{
  const toneSuffixes = ["", "FLIPPED", "FLIPPED REVERSED", "REVERSED"]
  function tones(name, ...components) {
    toneSuffixes.forEach((t, tn) => {
      add(`LNNZHYZ FINAL ${t} ${name}`)
    })
  }

for (const g of ["", "I", "U", "Y"]) {
    tones(g || "ZERO FINAL", g && `GLIDE SIGN ${g}`)
    for (const v of tA`E A`) {
      for (const c of [""].concat(tA`I U N NG R`))
        tones(`${g}${v}${c}`, g && `GLIDE SIGN ${g}`, v && `VOWEL SIGN ${v}`, c && `CODA SIGN ${c}`)
    }
  }
  tones("O", "VOWEL SIGN O")
  tones("ONG", "VOWEL SIGN O", "CODA SIGN NG")
  tones("EH", "VOWEL SIGN EH")
}
fill(4)

//label("LNNZHYZ Shidinn Extensions")
for (const l of tA`YJ NJ RZ NZ NG NGW NW DW TW GW KW`)
  add(`LNNZHYZ LETTER ${l}`)
fill(4)
for (const l of tA`OO II UU AI AU EU AN ANG EN ENG EI ZERO_FINAL`)
  add(`LNNZHYZ LETTER ${l}`)
fill(4)
for (const l of tA`B P M V J Q X YJ NJ Z C S RZ NZ NG N D T G K H W NGW NW DW TW GW KW F`) {
  add(`LNNZHYZ MODIFIER LETTER NARROW ${l}`)
  add(`LNNZHYZ MODIFIER LETTER FLIPPED NARROW ${l}`)
}
fill(4)
for (const l of tA`OO II UU IH/ IO IU UO UI`) {
  add(`LNNZHYZ FINAL ${l}`)
  add(`LNNZHYZ FINAL FLIPPED ${l}`)
}
fill(4)

//label("LNNCrypt Supplement")
for (const l of tA`A_WITH_DOUBLE_VERTICAL_LINE O_WITH_DOUBLE_VERTICAL_LINE I_WITH_VERTICAL_LINE I_WITH_DOUBLE_VERTICAL_LINE U_WITH_VERTICAL_LINE U_WITH_DOUBLE_VERTICAL_LINE EI_WITH_SINGLE_VERTICAL_LINE FOLDED_L S_WITH_DOUBLE_VERTICAL_LINE`)
  add(`LNNCRYPT LETTER ${l}`)
fill(4)

//label("(Reserved)")
fill(8)

//label("LNNScribble")
for (const l of tA`B P M F D T N L G K H J Q X R Z C S ZERO_INITIAL`) {
  add(`LNNSCRIBBLE LETTER ${l}`)
  add(`LNNSCRIBBLE CAPITAL LETTER ${l}`)
}
for (const l of tA`I U Y A E`)
  add(`LNNSCRIBBLE LETTER ${l}`)
for (const l of tA`N NG R`)
  add(`LNNSCRIBBLE MODIFIER LETTER ${l}`)
fill(4)

//label("LNN Legacy Ciphers")
for (const l of letters)
  add(`LNN_GENERATION_ONE_CIPHER/ LETTER ${l}`)
fill(4)
for (const l of letters.concat(tA`UE MU`))
  add(`LNN_GENERATION_TWO_CIPHER LETTER ${l}`)
fill(4)
for (const i of range(10))
  add(`LNN_GENERATION_TWO_CIPHER DIGIT ${numWords[i]}`)
fill(4)

//label("(Reserved)")
//fill(6)

function hex(cp) {
  return cp.toString(16).toUpperCase().padStart(4, "0")
}

signature("<text:text>")
action(({}, text) => [...text].map(c => c.codePointAt(0)).flatMap(cp => map.has(cp) ? hex(cp) + " " + map.get(cp) : []).join("\n") || h.i18n(".no-results"))
locale("zh-CN", { description: "查询 LNN 密文 PUA 编码字符名称", messages: { "no-results": "输入中未发现 LNN 密文 PUA 编码字符。" } })